import baseUrl from './baseUrl.js'
import { isFunction } from '@/utils/is.js'
import { cloneDeep, setObjToString } from '@/utils/common.js'
import store from '@/store'

const loginErrCode = [400, 401, 402, 403, 404] // 需重新登录CODE码
const whitelistUrl = [`/user/login`, `/exp/openId`] // 请求白名单,无需TOKEN,其它接口无TOKEN则被拦截

const transform = {
  requestBeforeHook: (config, options) => { // 请求前处理config
    config.header = config.header || {'content-type': 'application/x-www-form-urlencoded'};
    // 将token携带在headers中
    if (whitelistUrl.includes(config.url)) {
      config.header = { ...config.header, token: 'whitelist' }
    } else {
      const userInfo = store.state.userType === 0 ? uni.getStorageSync('expInfo') : uni.getStorageSync('userInfo');
      if (userInfo && userInfo.token) {
        config.header = { ...config.header, token: userInfo.token }
      }
    }

    const { apiURL, postJoinParamsToUrl } = options
    config.url = apiURL ? apiURL + config.url : config.url
    // 处理method请求大写--uni-app必须要大写
    config.method = config.method.toUpperCase()
    // post请求--参数需要拼接到url后面
    if (config.method === 'POST' && postJoinParamsToUrl) {
      config.url = setObjToString(config.url, config.data)
    }
    return config
  }
}

const getBaseUrl = function() {
  const { miniProgram } = uni.getAccountInfoSync();
  return process.env.NODE_ENV === 'production' && miniProgram.appId === 'wx238ad63939c8de76' ? baseUrl.production : baseUrl.development
}

export class VRequest {
  constructor(options) {
    this.options = options
  }

  /**
  * @description 获取options中的转化对象
  * @returns {Object} transform
  */
  getTransform() {
    const { transform } = this.options
    return transform
  }

  /**
  * @description request请求方法
  */
  request(config, options) {
    let conf = cloneDeep(config)

    const transform = this.getTransform()
    const { requestBeforeHook } = transform || {}
    const { requestOptions } = this.options
    // 合并对象
    const opt = Object.assign({}, requestOptions, options)
    // 处理请求前的config
    if (requestBeforeHook && isFunction(requestBeforeHook)) {
      conf = requestBeforeHook(conf, opt)
    }

    return new Promise(async (resolve, reject) => {
      if (!conf.header.token) {
        reject({ code: 500, msg: "缺少token,请求已拦截"});
        return
      }
      // 测试token过期
      // conf.header.token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoie1wieGlhb3l1aWRcIjpcImFhZDljNDk5MjZmZTRlOWM5YzYyNGE2ZTVlMTNkNjg2XCIsXCJoZWFkaW1nXCI6XCJodHRwczovL3lpamlhbi5vYnMuY24tc291dGgtNC5teWh1YXdlaWNsb3VkLmNvbS91bmlfYXBwL3VzZXIvMTY1Nzk0MTAzOTUwNy5wbmdcIixcIm5pY2tOYW1lXCI6XCLlrpjmlrlcIixcIm9wZW5pZFwiOlwib29NWHc1UndsdF9iSHc2UnpfY1VGTmhQRDMwRVwiLFwic2V4XCI6XCIxXCIsXCJtb2JpbGVcIjpcIjE1OTg2NzQ0ODE0XCIsXCJ1c2VyTmFtZVwiOlwi5a6Y5pa5XCIsXCJwYXJhbXNcIjp7fSxcInRva2VuXCI6XCJcIixcImJhbGFuY2VcIjoxMDAuMDgsXCJpZFwiOjgsXCJ0YWdcIjpcIuWGoOW_g-eXhSzlpJrliqjnl4cs6IOD55eFXCIsXCJ0eGltaWRcIjpcImVKeXJWZ3J4Q2RaTHJTaklMRXBWc2pJMk5EVTJNekF3MEFHTGxxVVdLVmtwR2VrWktFSDR4U25aaVFVRm1TbEtWb1ltQmdZbUJpWm01dVlRbWN5VTFMeVN6TFJNc0FZTG1QTE1kQ0RQUzc4a1A3dWl2S3JVM1RranlqTy15TWdwT3lMYkxNUzlQTnc4MWFzZzB0VENyTEtnd0N5d01zd2swaGFxc1NRekYqZ1dRek5UYzFNakMzTUxvMW9BWlc4d0x3X19cIixcInN0YXR1c1wiOlwiMFwifSJ9.Hscen70eKMo9_fbZGW8F9rj9mL2ospLropBj7lagdJQ'
      const [error, res] = await uni.request(conf)
      if (error && error.errMsg) {// 失败--系统或者网络方面的原因
        uni.showToast({ // 可以关闭loading
          title: '网络超时，请重试',
          icon: 'none'
        });
        reject(error)
      } else if (res && res.statusCode !== 200) {// 请求错误或者参数错误
        uni.showToast({ // 可以关闭loading
          title: res.data.msg || res.data.message || '抱歉，服务繁忙，请稍后再试或联系在线客服',
          icon: 'none'
        });
        reject(error);
      } else if ((res && res.data && res.data.code == 200) || opt.isTransformResult) { // 成功 或者 页面单独处理
        resolve(res.data)
      } else if (loginErrCode.includes(res.data.code)) { // 用户未登录 || 登录过期
        uni.showToast({ // 可以关闭loading
          title: '登录过期，请重新登录',
          icon: 'none'
        });
        store.commit("SET_USERINFO", {});
        uni.switchTab({ url: '/pages/index/index'});
        reject(error);
      } else { // 业务报错
        console.error(conf, '请求信息');
        uni.showToast({ // 可以关闭loading
          title: res.data.msg || res.data.message || '抱歉，服务繁忙，请稍后再试或联系在线客服',
          icon: 'none'
        });
        reject(res.data)
      }
    })
  }

}

export const requestInstance = new VRequest({
  transform,
  // 配置项--以下配置都能在独立的接口请求中被覆盖
  requestOptions: {
    // 是否需要对返回数据进行处理
    isTransformResult: false,
    // post请求的时候参数拼接在url上
    postJoinParamsToUrl: false,
    // 接口地址
    apiURL: getBaseUrl()
  }
})

// 将request的this指向VRequest
export default requestInstance.request.bind(requestInstance)